package com.view
{
	import flash.events.Event;
	
	import fr.seraf.wow.constraint.WSpringConstraint;
	import fr.seraf.wow.core.WOWEngine;
	import fr.seraf.wow.core.data.WVector;
	import fr.seraf.wow.primitive.WSphere;
	
	import org.papervision3d.core.geom.Lines3D;
	import org.papervision3d.core.geom.renderables.Line3D;
	import org.papervision3d.core.geom.renderables.Vertex3D;
	import org.papervision3d.core.utils.Mouse3D;
	import org.papervision3d.core.utils.virtualmouse.VirtualMouse;
	import org.papervision3d.lights.PointLight3D;
	import org.papervision3d.materials.ColorMaterial;
	import org.papervision3d.materials.WireframeMaterial;
	import org.papervision3d.materials.shadematerials.EnvMapMaterial;
	import org.papervision3d.materials.special.LineMaterial;
	import org.papervision3d.objects.primitives.Plane;
	import org.papervision3d.objects.primitives.Sphere;
	import org.papervision3d.view.BasicView;
	
	public class SceneContainer extends BasicView
	{
		//Variables
		private var wowBalls:Array;
		private var wowAnchorPoints:Array;
		private var wowConstraints:Array;
		private var wow:WOWEngine;
		
		private var pv3dBalls:Array;
		private var pv3dAnchorPoints:Array;
		private var pv3dMirrorBalls:Array;
		private var pv3dLinesArray:Array;
		private var pv3dLines:Lines3D;
		private var light:PointLight3D;
		private var vMouse:VirtualMouse;
		private var mous3D:Mouse3D;
		
		private var gravity:Number = -4;
		private var numBalls:Number = 5;
		private var center:Number = 0;
		private var ballHeight:Number = 50;
		private var ballSpacing:Number = 5;
		private var ballMass:Number = 1;
		private var ballElasticity:Number = .6;
		private var ballFriction:Number = .1;
		private var ballRadius:Number = 50;
		private var stiffness:Number = .1;
		
		
		//Construstor
		public function SceneContainer()
		{
			super(1024, 800 );
			this.initPhysics();
			this.init3D();
			this.addEventListener(Event.ENTER_FRAME, this.loop );
		}
		
		//Public methods
		
		//Private methods
		private function initPhysics():void
		{
			//keep the objects in an array, so we can access them later on
			wowBalls = new Array();
			wowAnchorPoints = new Array();
			wowConstraints = new Array();
			
			// init wow basics
			wow=new WOWEngine();
			wow.collisionResponseMode = wow.SELECTIVE;
			//add some gravity
			wow.addMasslessForce(new WVector(0,gravity,0));
			
			var wowBall:WSphere;
			var wowAnchorPoint1:WSphere;
			var wowAnchorPoint2:WSphere;
			var constraint:WSpringConstraint;
			
			var x:int = 0;
			var y:int = -ballHeight/2;
			var z:int = 0;
			var fixed:Boolean = false;
			
			//make the physics represenation of the balls
			for(var i:uint=0; i < numBalls; i++)
			{
				//add the ball
				fixed = false;
				wowBall = new WSphere(1+((i-center)*ballSpacing),y,z,ballRadius,fixed,ballMass,ballElasticity,ballFriction);
				wowBalls.push(wowBall);
				wow.addParticle(wowBall);
				
				//add the first anchorpoint 'holding' the ball
				fixed = true;
				wowAnchorPoint1 = new WSphere(x+((i-center)*ballSpacing),y+ballHeight,z-150,ballRadius,fixed);
				wowAnchorPoints.push(wowAnchorPoint1);
				wow.addParticle(wowAnchorPoint1);
				
				//add the second anchorpoint 'holding' the ball
				wowAnchorPoint2 = new WSphere(x+((i-center)*ballSpacing),y+ballHeight,z+150,ballRadius,fixed);
				wowAnchorPoints.push(wowAnchorPoint2);
				wow.addParticle(wowAnchorPoint2);
				
				//build the 'holding' mechanism by using constraints
				constraint = new WSpringConstraint(wowBall, wowAnchorPoint1,stiffness);
				wowConstraints.push(constraint);
				wow.addConstraint(constraint);
				
				constraint = new WSpringConstraint(wowBall, wowAnchorPoint2,stiffness);
				wowConstraints.push(constraint);
				wow.addConstraint(constraint);
			}
		}
		
		private function init3D():void
		{
			pv3dBalls = new Array();
			pv3dAnchorPoints = new Array();
			pv3dMirrorBalls = new Array();
			
			camera.y = 500;
		
			// init papervision basics
			/*view = new BasicView(stage.stageWidth, stage.stageHeight, true, true);
			view.camera.zoom = 10;
			view.camera.focus = 150;
			addChild(view);*/
			
			//use interactive 3dmouse
			/*vMouse = view.viewport.interactiveSceneManager.virtualMouse;
			mouse3D = view.viewport.interactiveSceneManager.mouse3D;
			Mouse3D.enabled = true;*/
			
			//create lines obj representing constraints between anchorpoints and balls
			pv3dLinesArray = new Array();
			pv3dLines = new Lines3D(new LineMaterial(0x00FF00,1));
			
			scene.addChild( pv3dLines );
			
			// create materials
			var wm:WireframeMaterial = new WireframeMaterial(0x00FF00, 1);
			
			//create the glas "table"
			var glasPane:Plane = new Plane( wm, 400, 600, 10, 10 );
			glasPane.rotationX = 270;
			glasPane.material.doubleSided = true;
			scene.addChild(glasPane, "glasPane");
			
			var pv3dBall:Sphere;
			var pv3dMirrorBall:Sphere;
			var pv3dAnchorPoint1:Sphere;
			var pv3dAnchorPoint2:Sphere;
			
			//create the 3d representation of the balls
			for(var i:uint=0; i < numBalls; i++)
			{
				//add the shiny little ball
				pv3dBall = new Sphere(new WireframeMaterial(0xaf8554),ballRadius+5,10,10);
				pv3dBall.material.interactive = true;
				pv3dBall.name = "pv3dBall"+i;
				pv3dBall.scale *=-1;
				scene.addChild(pv3dBall, "pv3dBall"+i);
				pv3dBalls.push(pv3dBall);
				
				//add the mirror ball
				/*pv3dMirrorBall = new Sphere(ballMirrorMaterial,ballRadius+2,10,10);
				view.scene.addChild(pv3dMirrorBall, "pv3dMirrorBall"+i);
				pv3dMirrorBalls.push(pv3dMirrorBall);*/
				
				//add the first anchorpoint 'holding' the ball
				pv3dAnchorPoint1 = new Sphere(new ColorMaterial(0x00FF00,1),1);
				scene.addChild(pv3dAnchorPoint1, "pv3dAnchorPoint1"+i);
				pv3dAnchorPoints.push(pv3dAnchorPoint1);
				pv3dAnchorPoint1.x = i * 50;
				
				//add the second anchorpoint 'holding' the ball
				pv3dAnchorPoint2 = new Sphere(new ColorMaterial(0x999999,0.5),1);
				scene.addChild(pv3dAnchorPoint2, "pv3dAnchorPoint2"+i);
				pv3dAnchorPoints.push(pv3dAnchorPoint2);
				pv3dAnchorPoint2.x = i * 50;
				pv3dAnchorPoint2.y = i * 50;
				
				//add lines from ball to both anchorpoints, coordinates are done later...
				pv3dLinesArray.push(new Line3D(pv3dLines,new LineMaterial(0x999999,1),1,
					new Vertex3D(0,0,0), new Vertex3D(0,0,0) ));
				pv3dLines.addLine(pv3dLinesArray[i*2]);
				pv3dLinesArray.push(new Line3D(pv3dLines,new LineMaterial(0x999999,1),1,
					new Vertex3D(0,0,0), new Vertex3D(0,0,0) ));
				pv3dLines.addLine(pv3dLinesArray[i*2+1]);
			}
		}
		
		private function syncRenderingToPhysics():void
		{
		/*	if(_dragging)
			{
				wowBalls[_actualDragObjID].px = mouse3D.x;
				wowBalls[_actualDragObjID].py = mouse3D.y;
			}*/
			
			//just reposition the moving parts...
			for(var i:uint=0; i < numBalls; i++)
			{
				pv3dBalls[i].x =- wowBalls[i].px;
				pv3dBalls[i].y =- wowBalls[i].py;
				pv3dBalls[i].z =- wowBalls[i].pz;
				//pv3dMirrorBalls[i].copyPosition(pv3dBalls[i]);
				//pv3dMirrorBalls[i].y = (pv3dMirrorBalls[i].y*-1)-250;
			}
		}


		
		//Event Handlers
		private function loop( $event:Event ):void
		{
			//do the physics stuff
			wow.step();
			
			//set viewable stuff to physics stuff
			syncRenderingToPhysics();
			
			//light.copyPosition(view.camera);
			
			//do some camera movement
			/*Camera3D(view.camera).hover(0, view.viewport.containerSprite.mouseX*0.003,
				(view.viewport.containerSprite.mouseY-400)*0.002);*/
			
			//do the 3d rendering stuff
			singleRender();
		}

	}
}